import 'package:boss/color_constant.dart';
import 'package:boss/ui/widget/menu/menu_constant.dart';
import 'package:hi_common/hi_common.dart';
import 'package:bot_toast/bot_toast.dart';
import 'package:bot_toast/src/toast_widget/toast_widget.dart';
import 'package:flutter/material.dart';

import 'menu_item.dart';

final BorderRadius _menuRadius = BorderRadius.circular(
  8.w,
);

typedef MenuBuilder = Function(BuildContext context, bool isShow);

class Menu extends StatefulWidget {
  final MenuBuilder builder;

  final List<String> items;

  final MenuEvent eventType;

  final MenuNip nip;

  final BorderRadius radius;

  final ValueChanged<int> onMenuItemTap;

  const Menu({
    Key key,
    @required this.builder,
    this.items,
    this.eventType = MenuEvent.tap,
    this.nip = MenuNip.bottomCenter,
    this.radius,
    this.onMenuItemTap,
  }) : super(key: key);

  @override
  _MenuState createState() => _MenuState();
}

class _MenuState extends State<Menu> {
  bool _isShow = false;
  CancelFunc _cancel;

  @override
  Widget build(BuildContext context) {
    Widget child = GestureDetector(
      onTap: widget.eventType == MenuEvent.tap ? _handleEvent : null,
      onLongPress: widget.eventType == MenuEvent.longPress ? _handleEvent : null,
      behavior: HitTestBehavior.translucent,
      child: widget.builder(context, _isShow),
    );

    return child;
  }

  _handleEvent() {
    if (_isShow) {
      setState(() {
        _isShow = false;
      });
      _cancel();
      _cancel = null;
      return;
    }

    setState(() {
      _isShow = true;
    });

    showAttachedWidget(
      targetContext: context,
      onlyOne: true,
      attachedBuilder: (cancel) {
        _cancel = cancel;
        return Container(
          width: 160.w,
          height: 100.w * widget.items.length,
          decoration: BoxDecoration(color: Colors.white, borderRadius: widget.radius ?? _menuRadius, boxShadow: [
            BoxShadow(
              color: ColorConstant.b1b1,
              blurRadius: 10.w,
            ),
          ]),
          child: ListView.separated(
            padding: EdgeInsets.all(0),
            shrinkWrap: true,
            physics: NeverScrollableScrollPhysics(),
            itemCount: widget.items.length,
            itemBuilder: (context, index) {
              var current = widget.items[index];

              return MenuItem(
                title: current,
                onTap: () {
                  _handleMenuItemEvent(index);

                  _cancel();
                },
              );
            },
            separatorBuilder: (context, index) {
              return index == widget.items.length
                  ? SizedBox()
                  : Padding(
                      padding: EdgeInsets.symmetric(
                        horizontal: 20.w,
                      ),
                      child: Divider(
                        color: ColorConstant.e6e6,
                        height: 1.px,
                      ),
                    );
            },
          ),
        );
      },
    );
  }

  _handleMenuItemEvent(int index) {
    if (widget.onMenuItemTap != null) {
      widget.onMenuItemTap(index);
    }
  }

  CancelFunc showAttachedWidget(
      {@required ToastBuilder attachedBuilder,
      WrapAnimation wrapAnimation,
      WrapAnimation wrapToastAnimation = attachedAnimation,
      BuildContext targetContext,
      Offset target,
      Color backgroundColor = Colors.transparent,
      double verticalOffset = 0.0,
      double horizontalOffset = 0.0,
      Duration duration,
      Duration animationDuration,
      Duration animationReverseDuration,
      PreferDirection preferDirection,
      bool ignoreContentClick = false,
      bool onlyOne = false,
      bool allowClick = true,
      bool enableSafeArea}) {
    assert(verticalOffset >= 0.0, 'must be a positive number');
    assert(horizontalOffset >= 0.0, 'must be a positive number');
    assert(!(targetContext != null && target != null), 'targetContext and target cannot coexist');
    assert(targetContext != null || target != null, 'targetContext and target must exist one');

    Rect targetRect;
    if (target == null) {
      RenderObject renderObject = targetContext.findRenderObject();
      if (renderObject is RenderBox) {
        final position = renderObject.localToGlobal(Offset.zero);
        targetRect = Rect.fromLTWH(position.dx, position.dy, renderObject.size.width, renderObject.size.height);
      } else {
        throw Exception('context.findRenderObject() return result must be RenderBox class');
      }
    } else {
      targetRect = Rect.fromLTWH(target.dx, target.dy, 0, 0); //点矩形
    }
    return BotToast.showAnimationWidget(
      allowClick: allowClick,
      clickClose: true,
      groupKey: '_attachedKey',
      crossPage: false,
      onlyOne: onlyOne,
      backgroundColor: backgroundColor,
      ignoreContentClick: ignoreContentClick,
      animationDuration: animationDuration ?? const Duration(milliseconds: 150),
      animationReverseDuration: animationReverseDuration,
      duration: duration,
      wrapAnimation: wrapAnimation,
      wrapToastAnimation: (controller, cancel, child) {
        controller.addStatusListener((status) {
          if (status == AnimationStatus.dismissed) {
            if (mounted)
              setState(() {
                _isShow = false;
              });
          }
        });
        return CustomSingleChildLayout(
          delegate: PositionDelegate(
              target: targetRect,
              verticalOffset: verticalOffset ?? 0,
              horizontalOffset: horizontalOffset ?? 0,
              enableSafeArea: enableSafeArea ?? true,
              preferDirection: preferDirection),
          child: wrapToastAnimation != null ? wrapToastAnimation(controller, cancel, child) : child,
        );
      },
      toastBuilder: attachedBuilder,
    );
  }
}
